<script>
import {Row,Col,Form,FormItem,Collapse, CollapseItem, Tabs, TabPane, Tooltip,Card} from 'element-ui'
import { cloneDeep, toDate,  getBeforeTime,getLaterTime,getScriptFunc, } from '../utils/index.js';
import { springEl } from "../utils/springEl.js"
import Render from './index.js';
import FormTipItem from './form-tip-item.vue';

const dyOptionsList = ['radio', 'checkbox', 'select', 'cascader', 'treeSelect'];
const layouts = {
  colFormItem(h, scheme) {
    const config = scheme.config;
    const listeners = buildListeners.call(this, scheme);
    let labelWidth = config.labelWidth ? `${config.labelWidth}px` : null;
    if (config.showLabel === false) labelWidth = '0';
    const Item =
          <div>
            <Render
              formData={this[this.data.formModel]}
              conf={scheme}
              formConf={this.data}
              {...{ on: listeners }}
              ref={config.identity === 'table' ? scheme.model : undefined}
              key={scheme.config.renderKey}
              relations={config.identity === 'table' ? this.relations : undefined}
            />
          </div>
    const visibility= !config.visibility || (Array.isArray(config.visibility) && config.visibility.includes('pc'));
    if (visibility && !config.hidden) {
      let toolTip = (
        <Col span={config.span} class={config.className}>
          {scheme.hidden ? (
            // 如果 hidden 为 true，直接渲染 Item
            Item
          ) : (
            // 如果 hidden 为 false，渲染 FormTipItem 并包裹 Item
            <FormTipItem
              label-width={labelWidth}
              prop={scheme.model}
              key={config.renderKey}
              tip-label={config.label ? config.tipLabel : ''}
              label={config.showLabel ? config.label : ''}
            >
              {Item}
            </FormTipItem>
          )}
        </Col>
      );
      if (config.identity === 'alert') {
        toolTip = (
          <Col span={config.span} class={config.className}>
            <FormTipItem
              label-width={labelWidth}
              prop={scheme.model}
              key={config.renderKey}
              tip-label={config.label ? config.tipLabel : ''}
              label={config.showLabel ? config.label : ''}
            >
              <div style="word-break: break-all">{Item}</div>
            </FormTipItem>
          </Col>
        );
      }
      if (config.identity === 'table') {
        toolTip = (
          <Col span={config.span} class={config.className}>
            <FormItem
              label-width={labelWidth}
              prop={scheme.model}
              key={config.renderKey}
              label={config.showLabel ? config.label : ''}
            >
              {Item}
            </FormItem>
          </Col>
        );
      }
      return toolTip;
    }
  },
  rowFormItem(h, scheme) {
    const listeners = buildListeners.call(this, scheme);
    const config = scheme.config;
    const visibility= !config.visibility || (Array.isArray(config.visibility) && config.visibility.includes('pc'));
    if (!visibility || scheme.hidden) return;
    if (scheme.config.identity === 'tab') {
      return (
        <Col span={scheme.config.span} class="mb-10px">
          <Tabs
            type={scheme.type}
            tab-position={scheme['tab-position']}
            model={scheme.config.active}
            {...{ on: listeners }}
          >
            {scheme.config.children.map((item, i) => {
              const child = renderChildren.call(this, h, item);
              return (
                <TabPane key={item.name} label={item.title}>
                  <Row>{child}</Row>
                </TabPane>
              );
            })}
          </Tabs>
        </Col>
      );
    }
    if (scheme.config.identity === 'collapse') {
      return (
        <Col span={scheme.config.span} class="mb-20px">
          <Collapse
            model={scheme.config.active}
            accordion={scheme.accordion}
            {...{ on: listeners }}
          >
            {scheme.config.children.map((item, i) => {
              const child = renderChildren.call(this, h, item);
              return (
                <CollapseItem
                  key={item.name}
                  title={item.title}
                  name={item.name}
                >
                  <Row>{child}</Row>
                </CollapseItem>
              );
            })}
          </Collapse>
        </Col>
      );
    }
    if (scheme.config.identity === 'tableGrid') {
      return (
        <Col span={scheme.config.span}>
          <Row gutter={scheme.config.gutter}>
            <table
              class="global-table-grid-box"
              style={{
                '--borderType': scheme.config.borderType,
                '--borderColor': scheme.config.borderColor,
                '--borderWidth': scheme.config.borderWidth + 'px',
              }}
            >
              <tbody>
                {scheme.config.children.map((item) => {
                  return (
                    <tr>
                      {item.config.children.map((it, colIndex) => {
                        const child = renderChildren.call(this, h, it);
                        return !it.config.merged
                          ? (
                            <td
                              colspan={it.config.colspan || 1}
                              rowspan={it.config.rowspan || 1}
                            >
                              <Col>
                                <Row gutter={scheme.config.gutter}>
                                  {child}
                                </Row>
                              </Col>
                            </td>
                          )
                          : (
                            ''
                          );
                      })}
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </Row>
        </Col>
      );
    }
    let child = renderChildren.apply(this, arguments);
    if (scheme.config.identity === 'table') {
      if (!scheme.hidden) this.tableRefs[scheme.model] = scheme;
      return layouts.colFormItem.call(this, h, scheme);
    }
    if (scheme.config.identity === 'card') {
      let toolTip = scheme.header;
      if (scheme.config.tipLabel) {
        toolTip = (
          <span slot="label">
            {scheme.header}
            <Tooltip placement="top" content={scheme.config.tipLabel}>
              <a
                class="el-icon-question global-tooltip-question"
                style="margin-left:4px"
              >
              </a>
            </Tooltip>
          </span>
        );
      }
      let header = '';
      if (scheme.header) {
        header = (
          <div slot="header">
            <span>{toolTip}</span>
          </div>
        );
      }
      return (
        <Col span={scheme.config.span} class="item-card">
          <Card shadow={scheme.shadow} header={scheme.header} class="mb-20px">
            {header}
            {child}
          </Card>
        </Col>
      );
    }
    if (scheme.config.identity === 'row') {
      if (scheme.type === 'flex') {
        child = (
          <Row type={scheme.type} justify={scheme.justify} align={scheme.align}>
            {child}
          </Row>
        );
      }
      return (
        <Col span={scheme.config.span}>
          <Row gutter={scheme.gutter}>{child}</Row>
        </Col>
      );
    }
    if (scheme.config.identity === 'flex') {
      if (scheme.type === 'flex') {
        child = (
          <Row type={scheme.type} justify={scheme.justify} align={scheme.align}>
            {child}
          </Row>
        );
      }
      return (
        <Col span={scheme.config.span}>
          <Row gutter={scheme.config.gutter} class={scheme.config.border ? 'drawing-item' : ''}>
            <span>{scheme.config.displayName} </span>
            <div style={scheme.flex}>{child}</div>
          </Row>
        </Col>
      );
    }
  },
};

function renderFrom(h) {
  const { formConfCopy } = this;
  let classStyle = [];
  if (formConfCopy.formStyle) classStyle.push(formConfCopy.formStyle);
  if (formConfCopy.className) classStyle = [...classStyle, ...formConfCopy.className];
  return (
    <Row gutter={formConfCopy.gutter} class={classStyle}>
      <Form
        size={formConfCopy.size}
        label-position={formConfCopy.labelPosition}
        disabled={formConfCopy.disabled}
        label-width={`${formConfCopy.labelWidth}px`}
        ref={formConfCopy.formRef}
        // model不能直接赋值 https://github.com/vuejs/jsx/issues/49#issuecomment-472013664
        props={{ model: this[formConfCopy.formModel] }}
        rules={this[formConfCopy.formRules]}
        nativeOnSubmit={(event) => {
          event.preventDefault();
        }}
      >
        {renderFormItem.call(this, h, formConfCopy.fields)}
      </Form>
    </Row>
  );
}


function renderFormItem(h, elementList) {
  return elementList.map((scheme) => {
    const config = scheme.config;
    const layout = layouts[config.layout];

    if (layout) {
      return layout.call(this, h, scheme);
    }
    throw new Error(`没有与${config.layout}匹配的layout`);
  });
}

function renderChildren(h, scheme) {
  const config = scheme.config;
  if (!Array.isArray(config.children)) return null;
  return renderFormItem.call(this, h, config.children);
}
function setValue(event, config, scheme) {
  this.$set(config, 'defaultValue', event);
  this.$set(this[this.data.formModel], scheme.model, event);
  this.buildFormula(this.formConfCopy.fields)
}
/**
 * 构建监听器对象，根据传入的方案（scheme）配置事件监听器。
 * 适用于绑定 select、radio、checkbox 等组件的 change 事件处理。
 *
 * @param {Object} scheme - 配置方案对象，包括组件配置、事件等。
 * @returns {Object} listeners - 事件监听器对象。
 */
function buildListeners(scheme) {
  const { config, on = {}, options, props = {} } = scheme; // 解构获取配置
  const listeners = {};

  // 遍历事件对象，动态生成事件处理函数
  Object.entries(on).forEach(([key, str]) => {
    const func = getScriptFunc.call(this, str); // 获取事件对应的函数
    if (!func) return;

    // 根据事件类型构建处理函数
    listeners[key] = (params) => {
      let data;
      if (key === 'change') {
        const param = params[0];

        // 处理 select、radio、checkbox 等组件的选项变化
        if (['select', 'radio', 'checkbox'].includes(config.identity)) {
          const isMultiple = scheme.multiple || config.identity === 'checkbox'; // 是否多选
          const valueProp = props.props?.value; // 获取选项值的属性名

          // 多选处理
          if (isMultiple) {
            data = param.map(item => options.find(option => option[valueProp] === item)).filter(Boolean);
          } else {
            // 单选处理
            data = options.find(option => option[valueProp] === param) || {};
          }
        } else if (config.identity === 'numInput') {
          // 处理数字输入的变化
          data = param;
        } else {
          // 处理其他类型的数据传递
          data = params.length > 1 ? params[1] : param;
        }

        // 执行事件回调函数，传入参数对象
        func.call(this, { data, ...this.parameter });
        this.handleRelation(scheme.model); // 调用关联处理
      } else {
        // 处理非 change 类型的事件
        func.call(this, { data: params[0], ...this.parameter });
      }
    };
  });

  // 监听 input 事件，用于处理数据更新
  listeners.input = (event) => setValue.call(this, event, config, scheme);

  return listeners;
}


export default {
  components: {
    Render,
    FormTipItem,
	Row,
	Col,
	Form,
	FormItem,
	Collapse,
	CollapseItem,
	Tabs,
	TabPane
  },
  provide() {
    return {
      parameter: this.parameter,
    };
  },
  props: {
    data: {
      type: Object,
      required: true,
    },
  },
  data() {
    const data = {
      formConfCopy: this.cloneFormConfCopyData(this.data),
      [this.data.formModel]: {},
      [this.data.formRules]: {},
      options: {},
      tableRefs: {},
      relations: {},
      isTableValid: false,
      timer:null
    };
    this.initCss(data.formConfCopy);
    this.initFormData(data.formConfCopy.fields, data[this.data.formModel]);
    this.initRelationForm(data.formConfCopy.fields);
    this.buildRules(data.formConfCopy.fields, data[this.data.formRules]);
    this.buildRelations(data.formConfCopy.fields, data.relations);
    this.$nextTick(() => {
      this.onLoad(data.formConfCopy);
    });
    return data;
  },
  computed: {
    formDataConf() {
      const name = this.data.formModel;
      return this[name];
    },
    parameter() {
      const oldFormData = this.formConfCopy.formData ? this.formConfCopy.formData : {};
      this[this.data.formModel].id = oldFormData.id || '';
      this[this.data.formModel].flowId = oldFormData.flowId || '';
      return {
        formData: this[this.data.formModel],
        setFormData: this.setFormData,
        setShowOrHide: this.setShowOrHide,
        setRequired: this.setRequired,
        setDisabled: this.setDisabled,
        request: this.request,
        getFieldOptions: this.getFieldOptions,
        setFieldOptions: this.setFieldOptions,
      };
    },
  },
  created() {
    this.buildFormula(this.formConfCopy.fields);
  },
  mounted() {
    this.initRelationData();
  },
  methods: {
    /**
       * 根据表达式计算结果
       * @param {Array} expression - 表达式数组，每个元素包含计算项、比较项和执行项
       * @returns {*} - 匹配条件的执行结果，如果无匹配条件则返回 null
       *
       * 该函数遍历表达式中的每一项，依次计算其值，并在满足条件时返回对应的执行结果。
    */
    getCalcResult(expression) {
      for (let item of expression) {
        // 计算两个比较项的值
        const value1 = this.getCalcValue(item.type1, item.value1);
        const value2 = this.getCalcValue(item.type2, item.value2);
        if (value1 === undefined || value1 === null || value2 === undefined || value2 === null) return null;
        // 检查两个值是否满足指定的比较条件
        if (this.getEqualsResult(value1, value2, item.equal)) {
          // 当条件匹配时，计算并返回执行表达式的结果
          return this.getCalcValue('EXPRESSION', item.execute);
        }
      }
      // 如果没有任何项满足条件，返回 null
      return null;
    },
    /**
     * 根据给定的类型和值计算结果
     * @param {String} type - 值的类型（'FIELD' | 'EXPRESSION' | 'CUSTOM'）
     * @param {*} value - 需要计算的值，具体含义取决于类型
     * @returns {*} - 根据类型返回的计算结果
     *
     * 该函数根据不同的类型执行相应的处理逻辑，并返回计算结果。
     * - 'FIELD'：返回表单模型中的字段值。
     * - 'EXPRESSION'：根据公式替换并执行表达式。
     * - 'CUSTOM'：直接返回给定的值。
     */
    getCalcValue(type, value) {
      // 判断类型为 'FIELD'，返回表单模型中的指定字段值
      if (type === 'FIELD') {
        return this[this.data.formModel][value];

      // 判断类型为 'EXPRESSION'，执行表达式替换并计算结果
      } else if (type === 'EXPRESSION') {
        // 替换公式中的占位符值为表单模型中的实际值
        const newValue = this.replaceFormulaValues(value, this[this.data.formModel]);
        // 使用 springEl 库执行替换后的表达式并返回结果
        return springEl().execute(newValue);

      // 判断类型为 'CUSTOM'，直接返回传入的值
      } else if (type === 'CUSTOM') {
        return value;

      // 如果类型不支持，弹出错误提示并记录错误类型
      } else {
        this.$message.error('不支持的字段类型：' + type);
        return null;  // 返回 null，避免函数未定义返回值
      }
    },
     /**
     * 将公式中的占位符替换为对象中的实际值
     * @param {String} formula - 包含占位符的公式字符串（占位符格式为 `#字段名`）
     * @param {Object} obj - 用于替换占位符的对象
     * @returns {String} - 替换后的公式字符串
     *
     * 该函数查找公式中以 `#` 开头的字段占位符，并用传入对象 `obj` 中的对应值替换。
     * 如果字段名在 `obj` 中不存在，则保留原始占位符。
     */
    replaceFormulaValues(formula, obj) {
      // 正则匹配 # 后跟随字母或下划线开头、由字母、数字或下划线组成的字段名
      const regex = /#([a-zA-Z_][a-zA-Z0-9_]*)/g;

      // 使用字符串替换方法，根据匹配的字段名在对象中查找实际值
      return formula.replace(regex, (match, p1) => {
        const key = p1; // 提取的字段名
        // 如果对象中存在对应的字段，则返回字段值；否则返回原占位符
        return obj[key] !== undefined ? obj[key] : match;
      });
    },

    /**
     * 根据给定的比较类型，判断两个值是否符合条件
     * @param {*} value1 - 第一个待比较的值
     * @param {*} value2 - 第二个待比较的值
     * @param {String} equal - 比较类型，支持的类型有 'GE', 'GT', 'EQ', 'LE', 'LT', 'NE', 'LK', 'NL', 'RG'
     * @returns {Boolean} - 比较结果，如果符合条件则返回 `true`，否则返回 `false`
     *
     * 该函数根据比较类型对两个值进行比较，并返回比较结果。
     */
    getEqualsResult(value1, value2, equal) {
      // 大于等于（GE）
      if (equal === 'GE') {
        return value1 >= value2;

      // 大于（GT）
      } else if (equal === 'GT') {
        return value1 > value2;

      // 等于（EQ）
      } else if (equal === 'EQ') {
        return value1 == value2;  // 使用 == 而非 ===，允许类型转换

      // 小于等于（LE）
      } else if (equal === 'LE') {
        return value1 <= value2;

      // 小于（LT）
      } else if (equal === 'LT') {
        return value1 < value2;

      // 不等于（NE）
      } else if (equal === 'NE') {
        return value1 != value2;  // 使用 != 而非 !==，允许类型转换

      // 包含（LK）：判断 value1 是否包含 value2
      } else if (equal === 'LK') {
        return value1 ? String(value1).indexOf(value2) > -1 : false;

      // 不包含（NL）：判断 value1 是否不包含 value2
      } else if (equal === 'NL') {
        return value1 ? String(value1).indexOf(value2) === -1 : true;

      // 范围（RG）：判断 value1 是否在 value2 范围内
      } else if (equal === 'RG') {
        return value1 >= value2[0] && value1 <= value2[1];
      // 不支持的比较方式
      } else {
        this.$message.error('不支持的比较方式：' + equal);
        return false;  // 默认返回 false
      }
    },
    /**
       * 根据给定的数据构建并设置条件公式
       * @param {Array} newVal - 包含要处理项的数组
       *
       * 该函数会遍历每个项，并根据不同的表达式类型计算结果，
       * 然后将结果设置到相应的属性上。如果项有子项，则递归处理子项。
   */
    buildFormula(newVal) {
      // 定义属性表达式和默认值的映射关系
      const expressions = [
        { key: 'disabled', expr: 'disabledExpression', defaultValue: 'defaultDisabled' },
        { key: 'hidden', expr: 'hiddenExpression', defaultValue: 'defaultHidden' },
        { key: 'required', expr: 'requiredExpression', defaultValue: 'defaultRequired', ruleUpdate: true },
        { key: 'maxlength', expr: 'maxLengthExpression', defaultValue: 'defaultRequired' },
        { key: 'defaultValue', expr: 'expressionTrigger', defaultValue: 'defaultValue' },
      ];

      /**
       * 计算表达式并设置目标属性
       * @param {Object} item - 当前处理的项
       * @param {String} key - 属性名称（如 'disabled', 'hidden' 等）
       * @param {String} expr - 表达式名称
       * @param {String} defaultValue - 默认值名称
       * @param {Boolean} ruleUpdate - 是否需要更新规则（用于 'required' 属性）
       */
      const calculateAndSet = (item, key, expr, defaultValue, ruleUpdate) => {
        // 根据表达式类型获取表达式值
        let expressionValue = item[expr];

        // 针对 'expressionTrigger' 类型特殊处理，找到编辑状态的表达式
        if (expr === 'expressionTrigger' && item.expressionTrigger?.length) {
          //找到属于前端计算类型
          const expressionItem = item.expressionTrigger.find(e => e.code === 'EDITING');
          expressionValue = expressionItem ? expressionItem.expression : null;
        }

        // 如果表达式值不存在则直接返回
        if (!expressionValue) return;

        // 调用自定义计算方法获取表达式计算结果
        const calcResult = this.getCalcResult(expressionValue);

        // 根据表达式类型确定目标对象
        const target = expr === 'expressionTrigger' ? item.config : item;
        // 如果计算结果不为空，则使用结果，否则使用默认值
        const result = calcResult !== null ? calcResult : item[defaultValue];

        // 动态设置目标属性
        this.$set(target, key, result);
        // 如果需要更新规则并且当前属性是 'required'，则调用更新规则方法
        if (ruleUpdate && key === 'required') {
          this.updateRules(item, result);
        }
      };

      /**
       * 递归处理项和其子项
       * @param {Object} item - 当前处理的项
       */
      const processItem = (item) => {
        // 遍历 expressions 列表，处理每个表达式属性
        expressions.forEach(({ key, expr, defaultValue, ruleUpdate }) => {
          calculateAndSet(item, key, expr, defaultValue, ruleUpdate);
        });

        // 如果当前项是行布局且有子项，则递归处理子项
        if (item.config?.layout === 'rowFormItem' && Array.isArray(item.config?.children)) {
          item.config.children.forEach(processItem);
        }
      };

      // 遍历 newVal 数组，逐项调用 processItem 进行处理
      newVal.forEach(processItem);
    },
    cloneFormConfCopyData(formConf) {
      for (let item of formConf.fields) {
        item.defaultDisabled = item.disabled
        item.defaultHidden = item.hidden
        item.defaultrRequired = item.required
      }
      return cloneDeep(formConf)
    },
    initRelationData() {
      const handleRelationFun = (list) => {
        list.forEach((cur) => {
          this.handleDefaultRelation(cur.model);
          if (cur.config.children) handleRelationFun(cur.config.children);
        });
      };
      handleRelationFun(this.formConfCopy.fields);
    },
    initCss(formCopy) {
      if (document.getElementById('styleId')) {
        document.getElementById('styleId').remove();
      }
      const classJson = formCopy.classJson;
      const head = document.getElementsByTagName('head')[0];
      const style = document.createElement('style');
      style.type = 'text/css';
      style.id = 'styleId';
      const html = classJson;
      style.innerText = html;
      head.appendChild(style);
    },
    initFormData(componentList, formData) {
      componentList.forEach((cur) => {
        const config = cur.config;
        if (cur.model) formData[cur.model] = config.defaultValue;
        if (cur.config.identity === 'table') return;
        if (config.children) this.initFormData(config.children, formData);
      });
    },
    updateRules(item, isRequired) {
      if (isRequired) {
        this.buildRules(cloneDeep(this.newVal), this.rules);
      }
    },
    /**
   * 该函数用于构建组件间的关系。
   * 该函递归数遍历组件列表，根据每个组件的类型，将它们与相应的字段关联起来。
   *
   * @param componentList 需要处理的组件列表
   * @param relations 一个用来存储组件间关系的对象，初始为空
   * @returns relations 构建的关系对象
   */
    buildRelations(componentList, relations) {
      // 遍历每个组件
      componentList.forEach((cur) => {
        const config = cur.config;

        // 处理动态选项（dyOptionsList）
        if (dyOptionsList.indexOf(config.identity) > -1) {
          if (config.dataType === 'dynamic' && config.templateJson && config.templateJson.length) {
            config.templateJson.forEach((e) => {
              if (e.relationField) {
                // 构建项
                const item = this.createRelationItem(cur, 'setOptions');
                this.addRelation(e.relationField, item, relations);
              }
            });
          }
        }

        // 处理用户选择组件
        if (config.identity === 'userSelect' && ['dep', 'pos', 'role', 'group'].includes(cur.selectType)) {
          if (cur.relationField) {
            const item = this.createRelationItem(cur, 'setUserOptions');
            this.addRelation(cur.relationField, item, relations);
          }
        }

        // 处理地址选择组件
        if (config.identity === 'address' && ['address', 'cities'].includes(cur.selectType)) {
          if (cur.relationField) {
            const item = this.createRelationItem(cur, 'setAddressOptions');
            this.addRelation(cur.relationField, item, relations);
          }
        }

        // 处理弹窗选择组件
        if (config.identity === 'popupSelect' && cur.templateJson && cur.templateJson.length) {
          cur.templateJson.forEach((e) => {
            if (e.relationField) {
              const item = this.createRelationItem(cur, 'setPopupOptions');
              this.addRelation(e.relationField, item, relations);
            }
          });
        }

        // 处理日期类型组件
        if (config.identity === 'date') {
          this.handleTimeFields(cur, config, 'start');
          this.handleTimeFields(cur, config, 'end');
          this.handleRelationField(cur, config.startRelationField, 'setDate', relations);
          this.handleRelationField(cur, config.endRelationField, 'setDate', relations);
        }

        // 处理时间类型组件
        if (config.identity === 'time') {
          const format = cur.format === 'HH:mm' ? 'HH:mm:00' : cur.format;
          this.handleTimeFields(cur, config, 'start', format);
          this.handleTimeFields(cur, config, 'end', format);
          this.handleRelationField(cur, config.startRelationField, 'setTime', relations);
          this.handleRelationField(cur, config.endRelationField, 'setTime', relations);
        }

        // 递归处理子组件
        if (config.children) this.buildRelations(config.children, relations);
      });
    },

    // 创建关系项
    createRelationItem(cur, opType) {
      return {
        ...cur,
        realVModel: cur.config.isSubTable ? cur.config.parentVModel + '-' + cur.model : cur.model,
        opType: opType,
      };
    },

    // 将项添加到关系对象中
    addRelation(relationField, item, relations) {
      if (relations.hasOwnProperty(relationField)) {
        const exists = relations[relationField].some((o) => o.realVModel === item.realVModel);
        if (!exists) {
          relations[relationField].push(item);
        }
      } else {
        relations[relationField] = [item];
      }
    },

    // 处理时间字段
    handleTimeFields(cur, config, fieldType, format = 'YYYY-MM-DD HH:mm:ss') {
      const timeType = `${fieldType}TimeRule`;
      const timeValueType = `${fieldType}TimeType`;
      const timeTargetType = `${fieldType}TimeTarget`;
      const timeValue = `${fieldType}TimeValue`;

      if (config[timeType]) {
        if (config[timeValueType] === 1) {
          cur[`${fieldType}Time`] = config[timeValue];
        } else if (config[timeValueType] === 3) {
          cur[`${fieldType}Time`] = toDate(new Date(), format);
        } else {
          let previousDate = '';
          if (config[timeValueType] === 4 || config[timeValueType] === 5) {
            previousDate = this.calculateTime(config[timeTargetType], config[timeValueType], config[timeValue]);
          }
          cur[`${fieldType}Time`] = toDate(previousDate, format);
        }
      }
    },

    // 计算时间
    calculateTime(target, timeType, timeValue) {
      let date;
      if (timeType === 4) {
        date = getBeforeTime(target, timeValue);
      } else if (timeType === 5) {
        date = getLaterTime(target, timeValue);
      }
      return date;
    },

    // 处理关系字段
    handleRelationField(cur, relationField, opType, relations) {
      if (relationField) {
        const item = this.createRelationItem(cur, opType);
        this.addRelation(relationField, item, relations);
      }
    },

    handleRelation(field) {
      if (!field) return;
      const currRelations = this.relations;
      for (const key in currRelations) {
        if (key === field) {
          for (let i = 0; i < currRelations[key].length; i++) {
            const e = currRelations[key][i];
            const model = e.realVModel || e.model;
            const config = e.config;
            const identity = config.identity;
            let defaultValue = '';
            if (
              ['checkbox', 'cascader'].includes(identity)
              || ([
                'select',
                'treeSelect',
                'popupSelect',
                'popupTableSelect',
                'userSelect',
              ].includes(identity)
                && e.multiple)
            ) {
              defaultValue = [];
            }
            if (model.includes('-')) {
              // 子表字段
              const tableVModel = model.split('-')[0];
              this.$refs[tableVModel]
                && this.$refs[tableVModel].$children[0]
                && this.$refs[tableVModel].$children[0].handleRelationForParent(
                  e,
                  defaultValue,
                );
            } else {
              this.setFormData(e.model, defaultValue);
              if (e.opType === 'setOptions') {
                const query = {
                  paramList: this.getParamList(
                    config.templateJson,
                    this[this.data.formModel],
                  ),
                };
                // getDataInterfaceRes(config.propsUrl, query).then(res => {
                //     const realData = res.data;
                //     this.setFieldOptions(e.model, realData);
                // });
              }
              if (e.opType === 'setUserOptions') {
                const value = this[this.data.formModel][e.relationField] || [];
                this.comSet(
                  'ableRelationIds',
                  e.model,
                  Array.isArray(value) ? value : [value],
                );
              }
              if (e.opType === 'setAddressOptions') {
                const value = this[this.data.formModel][e.relationField] || [];
                this.comSet(
                  'ableAddressIds',
                  e.model,
                  Array.isArray(value) ? value : [value],
                );
              }
              if (e.opType === 'setDate') {
                let startTime = '';
                let endTime = '';
                if (e.config.startTimeType === 2) {
                  startTime
                    = this[this.data.formModel][e.config.startRelationField] || 0;
                } else {
                  startTime = e.startTime;
                }
                if (e.config.endTimeType === 2) {
                  endTime
                    = this[this.data.formModel][e.config.endRelationField] || 0;
                } else {
                  endTime = e.endTime;
                }
                this.comSet('startTime', e.model, startTime);
                this.comSet('endTime', e.model, endTime);
              }
              if (e.opType === 'setTime') {
                let startTime = '';
                let endTime = '';
                if (e.config.startTimeType === 2) {
                  startTime
                    = this[this.data.formModel][e.config.startRelationField]
                    || '00:00:00';
                  if (startTime && startTime.split(':').length === 3) {
                    startTime = startTime;
                  } else {
                    startTime = startTime + ':00';
                  }
                } else {
                  startTime = e.startTime;
                }
                if (e.config.endTimeType === 2) {
                  endTime
                    = this[this.data.formModel][e.config.endRelationField]
                    || '23:59:59';
                  if (endTime && endTime.split(':').length === 3) {
                    endTime = endTime;
                  } else {
                    endTime = endTime + ':00';
                  }
                } else {
                  endTime = e.endTime;
                }
                this.comSet('startTime', e.model, startTime);
                this.comSet('endTime', e.model, endTime);
              }
            }
          }
        }
      }
    },
    /**
   * 处理默认关系逻辑，根据提供的 field 判断关系并执行相应的操作。
   * @param {string} field - 当前处理的字段名
   */
    handleDefaultRelation(field) {
      if (!field) return; // 如果没有提供 field，直接返回，避免不必要的处理

      const currRelations = this.relations; // 获取当前的关系配置，避免每次循环都访问 this.relations

      // 遍历所有关系，检查当前 key 是否与提供的 field 匹配
      for (const key in currRelations) {
        if (key === field) {

          // 遍历当前 key 下的所有关系项
          currRelations[key].forEach(e => {
            const model = e.realVModel || e.model; // 获取该关系的 model（优先使用 realVModel）
            const config = e.config; // 获取该关系的配置

            // 判断 model 是否包含 '-'，表示父子关系
            if (model.includes('-')) {
              const tableVModel = model.split('-')[0]; // 提取父级模型名

              // 检查父级模型是否存在，如果存在则调用 handleRelationForParent 方法处理
              if (this.$refs[tableVModel] && this.$refs[tableVModel].$children[0]) {
                this.$refs[tableVModel].$children[0].handleRelationForParent(e, '', true);
              }
            } else {
              // 如果关系是设置用户选项
              if (e.opType === 'setUserOptions') {
                const value = this[this.data.formModel][e.relationField] || [];
                this.comSet('ableRelationIds', e.model, Array.isArray(value) ? value : [value]);
              }
              // 如果关系是设置地址选项
              if (e.opType === 'setAddressOptions') {
                const value = this[this.data.formModel][e.relationField] || [];
                this.comSet('ableAddressIds', e.model, Array.isArray(value) ? value : [value]);
              }
              // 如果关系是设置日期
              if (e.opType === 'setDate') {
                let startTime = '';
                let endTime = '';
                // 根据配置判断起始时间和结束时间
                if (e.config.startTimeType === 2) {
                  startTime = this[this.data.formModel][e.config.startRelationField] || 0;
                } else {
                  startTime = e.startTime;
                }
                if (e.config.endTimeType === 2) {
                  endTime = this[this.data.formModel][e.config.endRelationField] || 0;
                } else {
                  endTime = e.endTime;
                }
                this.comSet('startTime', e.model, startTime);
                this.comSet('endTime', e.model, endTime);
              }
              // 如果关系是设置时间
              if (e.opType === 'setTime') {
                let startTime = '';
                let endTime = '';
                // 根据配置判断起始时间和结束时间
                if (e.config.startTimeType === 2) {
                  startTime = this[this.data.formModel][e.config.startRelationField] || '00:00:00';
                } else {
                  startTime = e.startTime;
                }
                if (e.config.endTimeType === 2) {
                  endTime = this[this.data.formModel][e.config.endRelationField] || '23:59:59';
                  if (endTime && endTime.split(':').length === 3) {
                    endTime = endTime;
                  } else {
                    endTime = endTime + ':00'; // 格式化时间字符串
                  }
                } else {
                  endTime = e.endTime;
                }
                if (startTime.split(':').length !== 3) {
                  startTime = startTime + ':00'; // 格式化起始时间
                }
                if (endTime.split(':').length !== 3) {
                  endTime = endTime + ':00'; // 格式化结束时间
                }
                this.comSet('startTime', e.model, startTime);
                this.comSet('endTime', e.model, endTime);
              }
            }
          });
        }
      }
    },

    getParamList(templateJson, formData) {
      for (let i = 0; i < templateJson.length; i++) {
        if (templateJson[i].relationField) {
          templateJson[i].defaultValue = formData[templateJson[i].relationField] || '';
        }
      }
      return templateJson;
    },
    initRelationForm(componentList) {
      componentList.forEach((cur) => {
        const config = cur.config;
        if (config.identity === 'relationFormAttr' || config.identity === 'popupAttr') {
          const relationKey = cur.relationField.split('_table_')[0];
          componentList.forEach((item) => {
            const noVisibility = Array.isArray(item.config.visibility) && !item.config.visibility.includes('pc');
            if (relationKey === item.model && (noVisibility || !!item.hidden) && !cur.model) {
              cur.hidden = true;
            }
          });
        }
        if (cur.config.children && cur.config.children.length) {
          this.initRelationForm(cur.config.children);
        }
      });
    },
    buildRules(componentList, rules) {
      componentList.forEach((cur) => {
        const config = cur.config;
        if (!Array.isArray(config.regList)) config.regList = [];
        if (cur.required) {
          const required = {
            required: cur.required,
            message: cur.placeholder,
          };
          if (Array.isArray(config.defaultValue) && cur.multiple) {
            required.type = 'array';
            required.message = `请至少选择一个${config.label}`;
          }
          required.message === undefined
            && (required.message = `${config.label}不能为空`);
          config.regList.push(required);
        }
        rules[cur.model] = config.regList.map((item) => {
          item.pattern
            && this.isRegExp(item.pattern)
            && (item.pattern = eval(item.pattern));
          item.trigger = config.trigger || 'blur';
          return item;
        });
        if (config.children && config.identity !== 'table') {
          this.buildRules(config.children, rules);
        }
      });
    },
    isRegExp(val) {
      try {
        return Object.prototype.toString.call(eval(val)) === '[object RegExp]';
      } catch {
        return false;
      }
    },
    onLoad(formConfCopy) {
      // 检查 formConfCopy 和 onLoad 函数是否定义
      if (!formConfCopy || !formConfCopy.funcs || !formConfCopy.funcs.onLoad) return;

      // 获取 onLoad 函数
      const onLoadFunc = getScriptFunc.call(this, formConfCopy.funcs.onLoad);

      // 确保 onLoadFunc 是一个函数
      if (typeof onLoadFunc !== 'function') return;

      // 执行 onLoad 函数
      onLoadFunc(this.parameter);
    },
    resetForm() {
      // this.$store.commit("generator/UPDATE_RELATION_DATA", {});
      this.formConfCopy = cloneDeep(this.data);
      this.$refs[this.data.formRef].resetFields();
      Object.keys(this.tableRefs).forEach((model) => {
        this.$refs[model]
          && this.$refs[model].$children
          && this.$refs[model].$children[0].resetTable();
      });
    },
    checkTableData() {
      let valid = true;
      Object.keys(this.tableRefs).forEach((model) => {
        if (this.$refs[model] && this.$refs[model].$children) {
          const res = this.$refs[model].$children[0].submit(); // 返回false或表单数据
          res ? (this[this.data.formModel][model] = res) : (valid = false);
        }
      });
      return valid;
    },
    request(url, method, data) {
      if (!url) return;
      // return request({
      //     url: url,
      //     method: method || "GET",
      //     data: data || {},
      // });
    },
    getFieldOptions(prop) {
      if (!prop) return [];
      const isChildTable = prop.indexOf('.') > -1;
      if (isChildTable) {
        const list = prop.split('.');
        if (this.$refs[list[0]] && this.$refs[list[0]].$children[0]) {
          const res = this.$refs[list[0]].$children[0].getTableFieldOptions(list[1]);
          return res;
        } else {
          return [];
        }
      } else {
        return this.options[prop + 'Options'] || [];
      }
    },
    setFormData(prop, value) {
      if (!prop || this[this.data.formModel][prop] === value) return;
      const isChildTable = prop.indexOf('.') > -1;
      if (isChildTable) {
        const list = prop.split('.');
        if (this.$refs[list[0]] && this.$refs[list[0]].$children[0]) {
          this.$refs[list[0]].$children[0].setTableFormData(list[1], value);
        }
      } else {
        this.comSet('defaultValue', prop, value);
        this[this.data.formModel][prop] = value;
      }
      this.handleRelation(prop);
    },
    setShowOrHide(prop, value) {
      const newVal = !!value;
      const isChildTable = prop.indexOf('.') > -1;
      if (!isChildTable) {
        this.comSet('noShow', prop, !newVal);
      } else {
        const list = prop.split('.');
        if (this.$refs[list[0]] && this.$refs[list[0]].$children[0]) {
          this.$refs[list[0]].$children[0].setTableShowOrHide(list[1], !newVal);
        }
      }
    },
    setRequired(prop, value) {
      const newVal = !!value;
      const isChildTable = prop.indexOf('.') > -1;
      if (!isChildTable) {
        this.comSet('required', prop, newVal);
        this.buildRules(this.formConfCopy.fields, this[this.data.formRules]);
      }
    },
    setDisabled(prop, value) {
      const newVal = !!value;
      const isChildTable = prop.indexOf('.') > -1;
      if (!isChildTable) {
        this.comSet('disabled', prop, newVal);
      }
    },
    setFieldOptions(prop, value) {
      const newVal = Array.isArray(value) ? value : [];
      const isChildTable = prop.indexOf('.') > -1;
      if (!isChildTable) {
        this.comSet('options', prop, newVal);
      }
    },
    comSet(field, prop, value) {
      if (!prop) return;
      const loop = (list) => {
        for (let i = 0; i < list.length; i++) {
          const item = list[i];
          if (item.model && item.model === prop) {
            switch (field) {
              case 'disabled':
                this.$set(item, field, value);
                break;
              case 'ableRelationIds':
                this.$set(item, field, value);
                break;
              case 'ableAddressIds':
                this.$set(item, field, value);
                break;
              case 'startTime':
                this.$set(item, field, value);
                break;
              case 'endTime':
                this.$set(item, field, value);
                break;
              case 'options':
                if (dyOptionsList.indexOf(item.config.identity) > -1) {
                  const isTreeSelect
                    = item.config.identity === 'treeSelect'
                    || item.config.identity === 'cascader';
                  isTreeSelect ? (item.options = value) : (item.options = value);
                }
                break;
              default:
                this.$set(item.config, field, value);
                break;
            }
            item.config.renderKey = +new Date() + item.model;
            break;
          }
          if (
            item.config
            && item.config.identity !== 'table'
            && item.config.children
            && Array.isArray(item.config.children)
          ) {
            loop(item.config.children);
          }
        }
      };
      loop(this.formConfCopy.fields);
    },
    beforeSubmit() {
      if (!this.formConfCopy?.funcs?.beforeSubmit) {
        return Promise.resolve();
      }
      const func = getScriptFunc.call(this, this.formConfCopy.funcs.beforeSubmit);
      if (!func) return Promise.resolve();
      return func(this.parameter);
    },
    afterSubmit() {
      if (!this.formConfCopy?.funcs?.afterSubmit) {
        return;
      }
      const func = getScriptFunc.call(this, this.formConfCopy.funcs.afterSubmit);
      if (!func) return;
      func(this.parameter);
    },
    submitForm(type) {
      this.isTableValid = this.checkTableData();
      try {
        this.beforeSubmit().then(() => {
          this.submit(type);
        });
      } catch (e) {
        this.submit(type);
      }
    },
    submit(type) {
      this.$refs[this.data.formRef].validate((valid) => {
        if (!valid) return false;
        if (!this.isTableValid) return false;
        // 触发submit事件
        this.$emit('submit', this[this.data.formModel], this.afterSubmit, type);
        return true;
      });
    },
    onCascaderChange(data, on) {
      if (!on || !on.change) return;
      const func = getScriptFunc.call(this, on.change);
      if (!func) return;
      func.call(this, { data, ...this.parameter });
    },
    onCascaderBlur(data, on) {
      if (!on || !on.blur) return;
      const func = getScriptFunc.call(this, on.blur);
      if (!func) return;
      func.call(this, { data, ...this.parameter });
    },
  },
  render(h) {
    return renderFrom.call(this, h);
  },
};
</script>

<style lang="scss" scoped>
.drawing-item {
  position: relative;
  cursor: move;

  &.unfocus-bordered:not(.active-from-item)>div:first-child {
    border: 1px dashed #ccc;
  }

  .el-form-item {
    border: 1px dashed #e2e0e0;
    padding: 10px;
  }
}
</style>